#include "TADComunicacion.h"

extern t_log* log;
extern int32_t EstaConsola;

/*

  El Proceso Emisor enviara un paquete NIPC extendido con los siguientes valores espec�ficos: 
  Type: 0 ( El 0 indica que el paquete es del tipo Handshake )
  Payload: El identificador del disco o nada si no es un disco.
*/

ent HandShakeEmisor(ent Sock,ent SoyDisco){	
	TMensaje *Mensaje;
	TMensaje *OtroMensaje;
	ent bytesRec=0,largo;
	time_t tActual;
	struct tm* tiempoGenerico;
	char cad[50];
	char MensajeP[1100];
	tActual = time(NULL);
	tiempoGenerico = localtime(&tActual);
	strftime(cad, 50, "%H%M%S", tiempoGenerico);
	Mensaje=(TMensaje*)calloc(1,sizeof(TMensaje));
	memset(Mensaje->payload,'\0',1100);
	sprintf(Mensaje->idDescriptor,"%s%010i",cad,rand()); // OBTENGO ASUNTO RANDOM
	
	if(SoyDisco){
		strcpy(Mensaje->payload,"Don Disco(1,2,3)"); // ESTE NOMBRE EN REALIDAD SE SACA DEL ARCHIVO DE CONFIGURACION
		Mensaje->payloadLength=strlen(Mensaje->payload);
	}
	else{
		Mensaje->payloadLength=0;
	}
	Mensaje->payloadDescriptor='0'; // TYPE CERO POR HANDSHAKE
	send(Sock,(void*)Mensaje,sizeof(struct TMensaje),0);  // ENVIO REQUEST DE HANDSHAKE	
	free(Mensaje);
	OtroMensaje=(TMensaje*)calloc(1,sizeof(TMensaje));
	
	while(bytesRec<=0){
		bytesRec=recv(Sock,(void*)OtroMensaje,sizeof(struct TMensaje),0); // RECIBO RESPUESTA DE HANDSHAKE
	}
	largo=OtroMensaje->payloadLength;
	strcpy(MensajeP,OtroMensaje->payload);
	free(OtroMensaje);
	if(largo==0){
		printf("HandShake realizado correctamente\n");
		return 1;
	}	
	else{

		printf("No se pudo realizar el HandShake\nCodigo de Error:%s",MensajeP); //Voy a devolver cero en la funcion despues afuera cierro el socket,etc.
		return 0;
	}
	
}


/*El Proceso Receptor segun quien sea ( Si soy un Raid o no) debe  responder con un paquete NIPC 
  con los siguientes valores espec�ficos:
  Type: 0 ( El 0 indica que el paquete es del tipo Handshake )
  Payload:
  Vac�o, por lo que Payload Length sera 0, en caso de que la conexi�n se correcta
  C�digo/Mensaje de error indicando que la negociaci�n fue fallida y el motivo de
  esto. Luego de enviar este paquete el Proceso RAID cierra la conexi�n.

*/


ent HandShakeReceptor(ent sock,ent cantDisp,ent SoyRaid,ent EstaP,ent *CantC,ent *CantH,ent *CantS){  //Si es un Raid me enteresa saber si tengo un planificador entonces tengo variable EstaP
   
	ent bytesRec=0,i=0,n=0,a=0,retorno=0,Largo,Info[3];
	TMensaje *TheirM,*MyM;
	char nombre[30],num[10],Tipo,cad[50],desicion;
	time_t tActual;
	struct tm* tiempoGenerico;

	TheirM=(TMensaje*)calloc(1,sizeof(TMensaje));
	memset(nombre, '\0',30);
	while(bytesRec<=0){
	  bytesRec=recv(sock, (void*)TheirM, sizeof(struct TMensaje), 0);  // RECIBO REQUEST
	}
	bytesRec= 0;
	MyM=(TMensaje*)calloc(1,sizeof(TMensaje));
	memset(MyM->payload,'\0',1100);
	strcpy(MyM->idDescriptor ,TheirM->idDescriptor);
	Largo= TheirM->payloadLength;
	//free(TheirM);
	MyM->payloadDescriptor='0';


	if(SoyRaid){ // SOY UN RAID
		if(cantDisp < 15){
			if(Largo != 0){ //ES UN PLANIFICADOR QUIEN ME HABLA
				//TODO OKEY
				strcpy(nombre,TheirM->payload);
				while(nombre[i] != '(')
					i++;
				i++;
				n=0;
				a=0;
				while(nombre[i] != ')'){
					n=0;
					while((nombre[i] != ',')&&(nombre[i]!= ')')){
						num[n]= nombre[i];
						n++;
						i++;
					}
					num[n]='\0';	
					Info[a]	= atoi(num);
					a++;
					if(nombre[i] != ')')
						i++;
					memset(num,'\0',10);
				}
				if(*CantC == -1 ) { // Es nuestro Disco Maestro
					*CantC=Info[0];
					*CantH=Info[1];
					*CantS=Info[2];
					if(EstaConsola)
						log_info(log, "RAID", "Message info: %s", "Se conecto el PPD Maestro");
					retorno =1;
				}
				else{	
					if((*CantC == Info[0])&&(*CantH == Info[1])&&(*CantS == Info[2])){
						MyM->payloadLength= 0;
						retorno =1;
						strcpy(MyM->payload,"Sincronizate"); //Esto es para que se sincronice o no el PPD
						if(EstaConsola)
							log_info(log, "RAID", "Message info: %s", "Se conecto un PPD y necesita ser sincronizado");
					}	
					else{
						strcpy(MyM->payload,"No se puede conectar planificador (CHS incorrecto)");
						MyM->payloadLength = strlen("No se puede conectar planificador (CHS incorrecto)");
						if(EstaConsola)
							log_error(log, "RAID", "Message error: %s", "No se puede conectar planificador (CHS incorrecto)");
						retorno= 0;
					}
				}		
				send(sock,(void*)MyM,sizeof(struct TMensaje),0); //ENVIO RESPONSE 
				free(MyM);
				free(TheirM);
				return retorno;
			}
			else{ //NO ES UN PLANIFICADOR QUIEN ME HABLA
				if(EstaP){//TENEMOS UN PLANIFICADOR 
					//TODO OKEY
					MyM->payloadLength= 0;
					send(sock,(void*)MyM,sizeof(struct TMensaje),0); //ENVIO RESPONSE
					free(MyM);
					return 1;					
				}
				else{// NO TENEMOS UN PLANIFICADOR
					if(EstaConsola)
						log_error(log, "RAID", "Message error: %s", "El RAID NO SE ENCUENTRA EN ESTADO ACTIVO");
					strcpy(MyM->payload,"El RAID NO SE ENCUENTRA EN ESTADO ACTIVO\n");
					MyM->payloadLength=strlen("El RAID NO SE ENCUENTRA EN ESTADO ACTIVO\n");
					send(sock,(void*)MyM,sizeof(struct TMensaje),0); //ENVIO RESPONSE 
					close(sock);
					free(MyM);
					return 0;
				}
			}
		}
		else{//TENEMOS MUCHOS DISPOSITIVOS
			if(EstaConsola)
				log_error(log, "RAID", "Message error: %s", "El RAID NO ADMITE MAS CONEXIONES");
			strcpy(MyM->payload,"El RAID NO ADMITE MAS CONEXIONES\n");
			MyM->payloadLength=strlen("El RAID NO ADMITE MAS CONEXIONES\n");
			send(sock,(void*)MyM,sizeof(struct TMensaje),0); //ENVIO RESPONSE 
			close(sock);
			free(MyM);
			free(TheirM);
			return 0;
		}
	}		
	else{ // NO SOY UN RAID	
			//POR LO PRONTO VAMOS A ACEPTAR SIEMPRE PUESTO QUE NO VEO CASO ENTRE PPD Y PFS QUE FALLE
			MyM->payloadLength= 0;
			send(sock,(void*)MyM,sizeof(struct TMensaje),0); //ENVIO RESPONSE 
			free(MyM);
			free(TheirM);
			return 1;
	}
	
	
}	
   
//FUNCION QUE ENVIA UN MENSAJE NIPC EXTENDIDO SIN ESPERAR RESPUESTA ( ASINCRONICAMENTE )
ent ComunicacionA(ent sock,char desc,char cadena[1100]){
	
	TMensaje *Mensaje;
	time_t tActual;
	struct tm* tiempoGenerico;
	char cad[50],respuesta2[1100];
	tActual = time(NULL);
	tiempoGenerico = localtime(&tActual);
	strftime(cad, 50, "%H%M%S", tiempoGenerico);
	Mensaje=(TMensaje*)calloc(1,sizeof(TMensaje));
	sprintf(Mensaje->idDescriptor,"%s%010i",cad,rand());
	Mensaje->payloadDescriptor = desc;
	Mensaje->payloadLength=(ent)strlen(cadena);
	strcpy(Mensaje->payload,cadena);
	send(sock,(void*)Mensaje,sizeof(TMensaje),0); //ENVIO CADENA
	printf("envie %s\n",Mensaje->payload);
	free(Mensaje);
	return 0;	
}


/*
Funcion especifica del Raid para obtener el tipo y nombre de los dispositivos que se estan conectando

*/
TInfo *ObtenerNombre(ent sock){
	
	TMensaje *Mensaje,*OtroMensaje;
	char Tipo;
	ent bytesRec=0;
	time_t tActual;
	TInfo *Info=(TInfo*)calloc(1,sizeof(TInfo));
	struct tm* tiempoGenerico;
	char cad[50],desicion;
	ent  i, stime,n,u=0,pos=0;
	tActual = time(NULL);
	tiempoGenerico = localtime(&tActual);
	strftime(cad, 50, "%H%M%S", tiempoGenerico);
	Mensaje=(TMensaje*)calloc(1,sizeof(TMensaje));		
	sprintf(Mensaje->idDescriptor,"%s%010i",cad,rand());
	Mensaje->payloadDescriptor='R';
	Mensaje->payloadLength=(ent)strlen("hola");
	strcpy(Mensaje->payload,"hola");
	send(sock,(void*)Mensaje,sizeof(struct TMensaje),0); //ENVIO SALUDO "HOLA" 
	free(Mensaje);
	OtroMensaje=(TMensaje*)calloc(1,sizeof(TMensaje));
	
	while(bytesRec<=0){
	  bytesRec=recv(sock, (void*)OtroMensaje, sizeof(struct TMensaje), 0);  // RECIBO REQUEST
	}
	
	strcpy(Info->Nombre,OtroMensaje->payload);	
	Info->Tipo=OtroMensaje->payloadDescriptor;
	free(OtroMensaje);
	return Info;
}


/*

Funcion que entrega el nombre al pedido "ObtenerNombre()" del RAID usada por PPD y PFS

*/
ent Nombre(ent Sock,char nombre[20],char Tipo){ // "Tipo" es 'F' si PFS o 'P' si Planificador	
	ent bytesRec= 0,valor;
	TMensaje *TheirM;
	TMensaje *MyM;
	
	TheirM=(TMensaje*)calloc(1,sizeof(TMensaje));
		
	while(bytesRec<=0){
		bytesRec=recv(Sock, (void*)TheirM, sizeof(struct TMensaje), 0); 
	}	
	
	if(!strcmp(TheirM->payload,"hola")){
		
		MyM=(TMensaje*)calloc(1,sizeof(TMensaje));
		strcpy(MyM->idDescriptor ,TheirM->idDescriptor);
		strcpy(MyM->payload,nombre);
		MyM->payloadLength=(ent)strlen(nombre);
		MyM->payloadDescriptor=Tipo;
		valor=send(Sock,(void*)MyM,sizeof(struct TMensaje),0);  
		free(MyM);
	    free(TheirM);				
	}
	return 0;	
}

	 


	
	










